package db;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import model.Product;

import org.apache.openjpa.persistence.OpenJPAPersistence;

public class OpenJPAConnector {

	private EntityManager e;
	private EntityTransaction t;
	private EntityManagerFactory fac;

	public OpenJPAConnector() {

		// Connecten OHNE Configfile
		fac = getWithoutConfig();

		// Connecten MIT Configfile
		// persistence.xml im META-INF-Ordner - 'openjpa' = persistence unit name
		// fac = Persistence.createEntityManagerFactory(
		// "openjpa", System.getProperties());

		e = fac.createEntityManager();
		t = e.getTransaction();

	}

	/*
	 * Diese Methode liest die Produkte aus der DB aus
	 */
	private void readFromDB() {

		t.begin();

		// Ausgabe begrenzt auf die neuesten 10 Produkte
		List<?> resultList = e
				.createQuery("SELECT p FROM Product p ORDER BY p.id DESC")
				.setMaxResults(10).getResultList();

		// Ausgelesene Produkte ausgeben
		for (Object o : resultList) {
			Product c = (Product) o;
			System.out.println(c.getId() + " " + c.getName() + " "
					+ c.getPrice() + " " + c.getQuantity());
		}

		t.commit();
	}

	/*
	 * Diese Methode fügt das Testprodukt in die Datenbank ein
	 */
	private void addProductToDatabase(Product productToInsert) {

		// Zum Einfügen muss eine neue Transaktion begonnen werden
		t.begin();
		e.persist(productToInsert); // Produkt in DB einfügen
		t.commit();
	}

	// Methode zum Connecten OHNE Configfile
	public static EntityManagerFactory getWithoutConfig() {

		// Verbindungsparameter angeben
		Map<String, String> map = new HashMap<String, String>();

		map.put("openjpa.ConnectionURL",
				"jdbc:postgresql://java.is.uni-due.de/ws1011");
		map.put("openjpa.ConnectionDriverName", "org.postgresql.Driver");
		map.put("openjpa.ConnectionUserName", "ws1011");
		map.put("openjpa.ConnectionPassword", "ftpw10");
		map.put("openjpa.RuntimeUnenhancedClasses", "supported");
		map.put("openjpa.jdbc.SynchronizeMappings", "false");

		// Persistente Klasse angeben
		map.put("openjpa.MetaDataFactory",
				"jpa(Types=" + model.Product.class.getName() + ")");

		// Folgendes wird benötigt, sobald wir mehr als eine persistente Klasse haben
		// Solange Product.class die einzige ist, geht es auch einfacher (siehe oben)
		// Klassen zur Registrierung angeben
//		List<Class<?>> types = new ArrayList<Class<?>>();
//		types.add(Product.class);
//		if (!types.isEmpty()) {
//			StringBuffer buf = new StringBuffer();
//			for (Class<?> c : types) {
//				if (buf.length() > 0)
//					buf.append(";");
//				buf.append(c.getName());
//			}
//			map.put("openjpa.MetaDataFactory", "jpa(Types=" + buf.toString() + ")");
//		}

		return OpenJPAPersistence.getEntityManagerFactory(map);

	}

	private void close() {
		// Alles schließen
		if (e.isOpen()) {
			e.close();
		}
		if (fac.isOpen()) {
			fac.close();
		}

	}

	// Zum Testen der obigen Methoden
	public static void main(String[] args) {
		Product p = null;
		// Neues Produkt zum Einfügen in die DB erstellen
		try {
			p = new Product("Tastatur", 50, 1);
		} catch (Exception e1) {
			e1.printStackTrace();
		}

		OpenJPAConnector openJPAC = new OpenJPAConnector();

		openJPAC.addProductToDatabase(p);

		openJPAC.readFromDB();

		openJPAC.close();
	}

}
